
// === uuAjax ===
// depend: uuMeta, uuURL
/*
window.UUJSONP_REQUEST_TIMEOUT = 10 * 1000  // min: 10000, unit: sec
window.UUJSONP_SUICIDE_TIMER   = 10 * 1000  // min: 10000, unit: sec
window.UUJSONP_CALLBACK_FUNC   = "callback" // JSONP callback function name

uuJsonp(url, callback, filer = 0x2)

filter {
  0x0: SILENCE
  0x1: READY( { pahse: 0x1, code: 0,          resp: ""        } )
  0x2: OK   ( { pahse: 0x2, code: 200,        resp: response  } )
  0x4: NG   ( { pahse: 0x4, code: bad status, resp: ""        } )
}
 */
(function() {
var _ajax, // inner namespace
    _mm = uuMeta,
    _win = window,
    _doc = document,
    _requestTimeout = _win.UUJSONP_REQUEST_TIMEOUT || (10 * 1000),
    _suicideTimer = _win.UUJSONP_SUICIDE_TIMER || (10 * 1000),
    _callbackFunc = _win.UUJSONP_CALLBACK_FUNC || "callback",
    _ie = _mm.ie,
    _mix = _mm.mix,
    _uuid = 0,   // request id
    _job = {};

// uuJsonp - JSONP async request
uuJsonp = function(url,      // @param URLString: request url
                   callback, // @param Function: callback function
                   filter) { // @param Number(= 0x2): callback filter
  filter = filter === void 0 ? 0x2 : filter;

  var hash = uuURL.parse(url),
      node = _doc.createElement("script"),
      head = _doc.getElementsByTagName("head")[0],
      rv = {
        id:     "jsonp" + ++_uuid, // request id
        phase:  0x1,      // request phase
        resp:   "",       // response
        code:   0,        // response code
        url:    hash.url  // request url
      };

  // add QueryString( "&callback=uuJsonp._job.jsonp1" )
  hash.hash[_callbackFunc] = "uuJsonp._job." + rv.id;
  hash.query = uuURL.buildQuery(hash.hash);

  function OK(json) {
    (filter & 2) &&
        callback(uu.mix(rv, { phase: 0x2, code: 200, resp: json }));
  }

  function NG(code) {
    (filter & 4) &&
        callback(uu.mix(rv, { phase: 0x4, code: code }));
  }

  function DIE() {
    head.removeChild(node);
    delete uuJsonp._job[rv.id];
  }

  uuJsonp._job[rv.id] = function(json, code) {
    if (!node._run++) {
      json ? OK(json)
           : NG(code || 404);
      setTimeout(DIE, _requestTimeout + _suicideTimer);
    }
  };

  (filter & 1) && callback(rv); // READY

  // <head>
  //   <script src="..." type="text/javascript" charset="utf-8"></script>
  // </head>
  node._run    = 0;
  node.type    = "text/javascript";
  node.charset = "utf-8";
  head.appendChild(node);
  node.setAttribute("src", uuURL.build(hash));

  // watchdog
  setTimeout(function() {
    uuJsonp._job[rv.id]("", 408); // 408 "Request Time-out"
  }, _requestTimeout);
};

_jsonp._job = {} // job db

// --- initialize ---

// --- export ---
_win.uuJsonp = _jsonp; // window.uuJsonp

})(); // uuJsonp scope
